﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EntityAndDomainLibrary.EntityModel;
using System.Data.Objects;
using log4net;
using log4net.Config;
using Log4NetLibrary;

namespace EntityAndDomainLibrary.DomainModel
{
    public class DataBaseAccess
    {
        #region Private Variables
        MeterProjectEntities domain = new MeterProjectEntities();
        ILogService logService; 
        #endregion

        public DataBaseAccess()
        {
            log4net.Config.XmlConfigurator.Configure();
            logService = new FileLogService(typeof(DataBaseAccess));
        }

        #region Public Methods
        public SystemSetting GetSystemSettings()
        {
            try
            {

                return domain.SystemSettings.FirstOrDefault();
            }

            catch (Exception ex)
            {
                logService.Error(ex.Message);
                return null;
            }
        }

        public IList<MeterDataDisplayed> GetAllTOUData(int meterid)
        {
            try
            {
                return ConvertDomainMeterDataToEntity(domain.TOUDatas.Where(x => x.meterpointid.Equals(meterid)).ToList<TOUData>());
            }

            catch (Exception ex)
            {
                logService.Error(ex.Message);
                return null;
            }
        }

        public bool SaveTOUDatas(TOUData data)
        {
            try
            {
                data.last_modified_date = DateTime.Now;

                TOUData _data = domain.TOUDatas.Where(x => x.meterpointid == data.meterpointid &&
                                         x.qtytypeid == data.qtytypeid &&
                                         x.date_time == data.date_time).FirstOrDefault();

                if (_data == null)
                {
                    if (domain.TOUStatustypes.Where(x => x.statusid == data.statusid).FirstOrDefault() == null)
                    {
                        TOUStatustype status = new TOUStatustype();
                        status.statusid = Convert.ToInt32(data.statusid);

                        domain.TOUStatustypes.AddObject(status);
                    }

                    domain.TOUDatas.AddObject(data);

                }

                else
                {
                    _data.value = data.value;
                    _data.statusid = data.statusid;
                    _data.last_modified_date = data.last_modified_date;
                }
                domain.SaveChanges();
                return true;
            }

            catch (Exception ex)
            {
                logService.Error(ex.Message);
                return false;
            }
        }

        public Meterpoint GetMeterPtByName(String metername)
        {
            try
            {
                Meterpoint mt =domain.Meterpoints.SingleOrDefault(x => x.name.Contains(metername));
               
                if(mt==null)
                {
                   mt = new Meterpoint();
                   mt.name = metername;
                   
                    mt.location = metername;
                    mt.meterpointid = domain.Meterpoints.OrderByDescending(m => m.meterpointid).Select(x => x.meterpointid).FirstOrDefault()+1;
                    SaveMeterPt(mt);

                    mt = domain.Meterpoints.SingleOrDefault(x => x.name.Contains(metername));
                }

                return mt;
            }

            catch (Exception ex)
            {
                logService.Error(ex.Message);
                return null;
            }
        }

        public TOUDatatype GetDatatypeByName(String datatypeName)
        {
            try
            {
                return domain.TOUDatatypes.SingleOrDefault(x => x.description.ToUpper().Contains(datatypeName));
            }

            catch (Exception ex)
            {
                logService.Error(ex.Message);
                return null;
            }
        }

        public IList<MeterDataDisplayed> GetLastUpdatedTouData()
        {
            try
            {
                TOUData data = domain.TOUDatas.OrderByDescending(x => x.date_time).FirstOrDefault();
                DateTime dt = data.date_time;

                return ConvertDomainLatestMeterDataToEntity(domain.TOUDatas.Where(x => x.date_time == dt).ToList<TOUData>());
            }

            catch (Exception ex)
            {
                logService.Error(ex.Message);
                return null;
            }
        }

        public DateTime GetLatestDate()
        {
            try
            {
                return domain.TOUDatas.OrderByDescending(x => x.date_time).FirstOrDefault().date_time;
            }

            catch (Exception ex)
            {
                logService.Error(ex.Message);
                return DateTime.Now;
            }
        }

        public IList<MeterDataDisplayed> GetTOUDataByDate(DateTime startdate, DateTime enddate, int meterid)
        {
            try
            {
                DateTime _startDate;
                DateTime _endDate;
                IList<TOUData> _listtempdata;

                _startDate = new DateTime(startdate.Year, startdate.Month, startdate.Day, 00, 00, 00);
                _endDate = new DateTime(enddate.Year, enddate.Month, enddate.Day, 00, 00, 00);

                _listtempdata = domain.TOUDatas.Where(o => EntityFunctions.CreateDateTime
                                                            (o.date_time.Year,
                                                            o.date_time.Month,
                                                            o.date_time.Day, 00, 00, 00)
                                                            >= _startDate &&
                                                            EntityFunctions.CreateDateTime
                                                            (o.date_time.Year,
                                                            o.date_time.Month,
                                                            o.date_time.Day, 00, 00, 00)
                                                            <= _endDate &&
                                                            o.meterpointid == meterid).ToList();


                return ConvertDomainMeterDataToEntity(_listtempdata);
            }

            catch (Exception ex)
            {
                logService.Error(ex.Message);
                return null;
            }

        }

        public IList<Output> GetTOUDataByDateForOutput(DateTime startdate)
        {
            try
            {
                DateTime _startDate;
                IList<TOUData> _listtempdata;

                _startDate = new DateTime(startdate.Year, startdate.Month, startdate.Day, 00, 00, 00);
              

                _listtempdata = domain.TOUDatas.Where(o => EntityFunctions.CreateDateTime
                                                            (o.date_time.Year,
                                                            o.date_time.Month,
                                                            o.date_time.Day, 00, 00, 00)
                                                            >= _startDate &&
                                                            EntityFunctions.CreateDateTime
                                                            (o.date_time.Year,
                                                            o.date_time.Month,
                                                            o.date_time.Day, 00, 00, 00)
                                                            <= _startDate).ToList();
                                                           


                return ConvertDomainMeterDataToOuputData(_listtempdata);
            }

            catch (Exception ex)
            {
                logService.Error(ex.Message);
                return null;
            }

        }

        public IList<Meterpoint> GetAllMeterpoint()
        {
            try
            {
                return domain.Meterpoints.ToList<Meterpoint>();
            }

            catch (Exception ex)
            {
                logService.Error(ex.Message);
                return null;
            }
        }

        public void SaveMeterPt(Meterpoint meterpt)
        {
            try
            {
                Meterpoint _meterpt = domain.Meterpoints.Where(x => x.meterpointid == meterpt.meterpointid).FirstOrDefault();

                if (_meterpt == null)
                {
                    domain.Meterpoints.AddObject(meterpt);

                }

                else
                {
                    _meterpt.name = meterpt.name;
                    _meterpt.location = meterpt.location;
                }
                
                domain.SaveChanges();

            }

            catch (Exception ex)
            {
                logService.Error(ex.Message);
                //return null;
            }

        }

        public void SaveSystemSettings(SystemSetting systemsetting)
        {
            try
            {
                SystemSetting system = GetSystemSettings();
                domain.DeleteObject(system);

                domain.SaveChanges();
                domain.SystemSettings.AddObject(systemsetting);
                domain.SaveChanges();
            }

            catch (Exception ex)
            {
                logService.Error(ex.Message);

            }
        }

        public IList<ReportData> GetReportData(DateTime startdate, DateTime enddate, int meterid =0)
        {
            try
            {
                DateTime _startDate;
                DateTime _endDate;
                IList<TOUData> _listtempdata;

                _startDate = Convert.ToDateTime(startdate);
                _endDate = Convert.ToDateTime(enddate);


                  _listtempdata = domain.TOUDatas.Where(o => EntityFunctions.CreateDateTime
                                                                (o.date_time.Year,
                                                                o.date_time.Month,
                                                                o.date_time.Day, 00, 00, 00)
                                                                >= EntityFunctions.CreateDateTime(
                                                                startdate.Year,
                                                                startdate.Month,
                                                                startdate.Day, 00, 00, 00) &&
                                                                EntityFunctions.CreateDateTime
                                                                (o.date_time.Year,
                                                                o.date_time.Month,
                                                                o.date_time.Day, 00, 00, 00)
                                                                <= EntityFunctions.CreateDateTime(
                                                                enddate.Year,
                                                                enddate.Month,
                                                                enddate.Day, 00, 00, 00) &&
                                                                o.meterpointid == meterid).ToList();
                

                return ConvertDomainMeterDataToReportData(_listtempdata);
                //}
            }

            catch (Exception ex)
            {
                logService.Error(ex.Message);
                return null;

            }
        }

        public FileArchive GetFileArchive(string location)
        {
            try
            {
                return domain.FileArchives.Where(x => x.filelocation.Equals(location)).FirstOrDefault();
            }

            catch (Exception ex)
            {
                logService.Error(ex.Message);
                return null;
            }
        }

        public FileArchive SaveFileArchive(string location)
        {
            try
            {
                FileArchive _file = GetFileArchive(location);

                if (_file == null)
                {
                    _file = new FileArchive();
                    _file.filelocation = location;

                    domain.FileArchives.AddObject(_file);
                    domain.SaveChanges();
                }

                return _file;
            }

            catch (Exception ex)
            {
                logService.Error(ex.Message);
                return null;

            }
        } 
        #endregion

        #region Helpers
        private IList<MeterDataDisplayed> ConvertDomainLatestMeterDataToEntity(IList<TOUData> listToudata)
        {
            try
            {
                IList<Meterpoint> _listmeterpts = GetAllMeterpoint();
                IList<MeterDataDisplayed> _listenity = new List<MeterDataDisplayed>();

                foreach (Meterpoint mpt in _listmeterpts)
                {
                    MeterDataDisplayed data = null;
                    IList<TOUData> _listtempdata = listToudata.Where(x => x.meterpointid == mpt.meterpointid).ToList();
                    if (_listtempdata != null && _listtempdata.Count() > 0)
                    {


                        foreach (TOUData tempdata in _listtempdata)
                        {
                            if (data == null)
                            {
                                data = new MeterDataDisplayed();
                                data.MeterName = tempdata.Meterpoint.name;
                            }

                            if (tempdata.TOUDatatype.description.Contains("+A"))
                                data.ImpwH = tempdata.value;

                            else if (tempdata.TOUDatatype.description.Contains("-A"))
                                data.ExpwH = tempdata.value;

                            else if (tempdata.TOUDatatype.description.Contains("+R"))
                                data.ImpVarH = tempdata.value;

                            else if (tempdata.TOUDatatype.description.Contains("-R"))
                                data.ExpVarH = tempdata.value;
                        }
                    }

                    if (data != null)
                        _listenity.Add(data);
                }

                return _listenity;
            }

            catch (Exception ex)
            {
                logService.Error(ex.Message);
                return null;

            }
        }

        private IList<MeterDataDisplayed> ConvertDomainMeterDataToEntity(IList<TOUData> listToudata)
        {
            try
            {
                IList<MeterDataDisplayed> _listenity = new List<MeterDataDisplayed>();
                List<DateTime> _removallist = new List<DateTime>();

                foreach (TOUData tempdata in listToudata)
                {
                    MeterDataDisplayed data = null;

                    if (_removallist.Where(x => x == tempdata.date_time).Count().Equals(0))
                    {

                        IList<TOUData> _listIdenticalRecords = listToudata.Where
                                            (x => x.date_time == tempdata.date_time).ToList();

                        if (data == null)
                        {
                            data = new MeterDataDisplayed();
                            data.MeterName = tempdata.Meterpoint.name;

                            data.TimeStamp = tempdata.date_time;
                            data.UpdatedDateTime = tempdata.last_modified_date;

                            _removallist.Add(tempdata.date_time);
                        }

                        foreach (TOUData _temp in _listIdenticalRecords)
                        {
                            if (_temp.TOUDatatype.description.Contains("+A"))
                                data.ImpwH = _temp.value;

                            else if (_temp.TOUDatatype.description.Contains("-A"))
                                data.ExpwH = _temp.value;

                            else if (_temp.TOUDatatype.description.Contains("+R"))
                                data.ImpVarH = _temp.value;

                            else if (_temp.TOUDatatype.description.Contains("-R"))
                                data.ExpVarH = _temp.value;
                        }
                        if (data != null)
                            _listenity.Add(data);
                    }



                }

                return _listenity;
            }

            catch (Exception ex)
            {
                logService.Error(ex.Message);
                return null;

            }
        }

        private IList<ReportData> ConvertDomainMeterDataToReportData(IList<TOUData> listdata)
        {
            try
            {
                IList<ReportData> _listrptdata = new List<ReportData>();

                foreach (TOUData tempdata in listdata)
                {
                    ReportData data = new ReportData();
                    data.TimeStamp = tempdata.date_time;

                    data.Value = tempdata.value;

                    switch (Convert.ToInt32(tempdata.qtytypeid))
                    {
                        case 1:
                            data.DataType = "ImpWh";
                            break;

                        case 2:
                            data.DataType = "ExpWh";
                            break;

                        case 3:
                            data.DataType = "ImpVarh";
                            break;

                        case 4:
                            data.DataType = "ExpVarh";
                            break;
                    }

                    _listrptdata.Add(data);
                }

                return _listrptdata;
            }

            catch (Exception ex)
            {
                logService.Error(ex.Message);
                return null;

            }
        }

        private IList<Output> ConvertDomainMeterDataToOuputData(IList<TOUData> listdata)
        {
            try
            {
                IList<Output> _listrptdata = new List<Output>();

                foreach (TOUData tempdata in listdata)
                {
                    Output data = new Output();
                    data.Name = "\"" + tempdata.date_time.ToLongDateString() + "\"";

                    data.Metername = "\"" + tempdata.Meterpoint.name + "_" + tempdata.TOUDatatype.Unit + "\"";
                    data.Value = "\"" + tempdata.value.ToString() + "\"";

                    data.Constant = "\"" + "100" + "\"";
                    _listrptdata.Add(data);
                }

                return _listrptdata;
            }

            catch (Exception ex)
            {
                logService.Error(ex.Message);
                return null;

            }
        }
    } 
        #endregion
}
